package com.zbkj.admin.config;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
public class WechatAccessTokenResponseClient implements OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> {
    private final RestTemplate restTemplate = createRestTemplate();

    @Override
    public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest request) {
        log.info("==== 进入微信Token客户端 ===="); // 添加入口日志
        log.info("客户端ID: {}", request.getClientRegistration().getClientId());
        log.info("Token端点: {}", request.getClientRegistration().getProviderDetails().getTokenUri());
        // 1. 构建微信请求参数
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("appid", request.getClientRegistration().getClientId());
        params.add("secret", request.getClientRegistration().getClientSecret());
        params.add("code", request.getAuthorizationExchange().getAuthorizationResponse().getCode());
        params.add("grant_type", "authorization_code");
        log.debug("请求微信Token参数: {}", params);
        UriComponents build = UriComponentsBuilder.fromUri(URI.create(request.getClientRegistration().getProviderDetails().getTokenUri()))
                .queryParams(params)
                .build();
        // 2. 发送请求到微信服务器
        ResponseEntity<String> response = restTemplate.getForEntity(
                build.toUriString(), String.class
        );

        // 3. 处理微信响应
        if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null) {
            throw new RuntimeException("微信授权失败: " + response.getBody());
        }
        Map<String, Object> responseMap = response.getBody().startsWith("{") ? JSON.parseObject(response.getBody(), Map.class) : null;
        checkWechatError(responseMap);
        log.info("微信授权成功，openid: {}", responseMap.get("openid"));
        // 4. 转换为 Spring Security 标准响应
        return OAuth2AccessTokenResponse.withToken((String) responseMap.get("access_token"))
                .tokenType(OAuth2AccessToken.TokenType.BEARER)
                .expiresIn(Long.parseLong(responseMap.get("expires_in").toString()))
                .scopes(Collections.singleton("snsapi_userinfo"))
                .additionalParameters(extractAdditionalParams(responseMap))
                .build();
    }

    // 创建带超时配置的 RestTemplate
    private RestTemplate createRestTemplate() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(10_000);
        factory.setReadTimeout(30_000);
        RestTemplate template = new RestTemplate(factory);
        template.setErrorHandler(new WechatErrorHandler());
        return template;
    }

    // 构建微信要求的请求头
    private HttpHeaders buildHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        return headers;
    }

    // 提取微信返回的额外参数（openid/unionid）
    private Map<String, Object> extractAdditionalParams(Map<String, Object> responseMap) {
        Map<String, Object> params = new HashMap<>();
        params.put("openid", responseMap.get("openid"));
        if (responseMap.containsKey("unionid")) {
            params.put("unionid", responseMap.get("unionid"));
        }
        return params;
    }

    // 检查微信返回的错误码
    private void checkWechatError(Map<String, Object> response) {
        if (response.containsKey("errcode")) {
            int errcode = (int) response.get("errcode");
            if (errcode != 0) {
                throw new RuntimeException("微信授权失败: " + response.get("errmsg"));
            }
        }
    }

    // 自定义错误处理器
    private static class WechatErrorHandler extends DefaultResponseErrorHandler {
        @Override
        public void handleError(ClientHttpResponse response) throws IOException {
            String body = StreamUtils.copyToString(response.getBody(), StandardCharsets.UTF_8);
            throw new RuntimeException("微信接口调用异常: " + body);
        }
    }
}
